home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / Src / Ch11 / LeastSq3.frm (.txt) < prev    next >
Visual Basic Form  |  1999-06-12  |  8KB  |  247 lines

  1. VERSION 5.00
  2. Begin VB.Form frmLeastSq3 
  3.    Caption         =   "LeastSq3"
  4.    ClientHeight    =   5310
  5.    ClientLeft      =   2085
  6.    ClientTop       =   615
  7.    ClientWidth     =   4830
  8.    LinkTopic       =   "Form1"
  9.    PaletteMode     =   1  'UseZOrder
  10.    ScaleHeight     =   5310
  11.    ScaleWidth      =   4830
  12.    Begin VB.TextBox txtDegree 
  13.       Height          =   285
  14.       Left            =   600
  15.       TabIndex        =   3
  16.       Text            =   "4"
  17.       Top             =   5010
  18.       Width           =   495
  19.    End
  20.    Begin VB.CommandButton cmdGo 
  21.       Caption         =   "Go"
  22.       Default         =   -1  'True
  23.       Enabled         =   0   'False
  24.       Height          =   375
  25.       Left            =   2040
  26.       TabIndex        =   1
  27.       Top             =   4920
  28.       Width           =   615
  29.    End
  30.    Begin VB.PictureBox picCanvas 
  31.       AutoRedraw      =   -1  'True
  32.       Height          =   2535
  33.       Left            =   120
  34.       ScaleHeight     =   165
  35.       ScaleMode       =   3  'Pixel
  36.       ScaleWidth      =   229
  37.       TabIndex        =   0
  38.       Top             =   120
  39.       Width           =   3495
  40.    End
  41.    Begin VB.Label Label1 
  42.       Caption         =   "Degree"
  43.       Height          =   255
  44.       Left            =   0
  45.       TabIndex        =   2
  46.       Top             =   5040
  47.       Width           =   615
  48.    End
  49. Attribute VB_Name = "frmLeastSq3"
  50. Attribute VB_GlobalNameSpace = False
  51. Attribute VB_Creatable = False
  52. Attribute VB_PredeclaredId = True
  53. Attribute VB_Exposed = False
  54. Option Explicit
  55. Private NumPts As Integer
  56. Private PtX() As Single
  57. Private PtY() As Single
  58. ' Perform Gaussian elimination on this array.
  59. ' Return True if there is a solution.
  60. Private Function GaussianEliminate(coeff() As Single) As Boolean
  61. Dim max_row As Integer
  62. Dim max_col As Integer
  63. Dim row As Integer
  64. Dim col As Integer
  65. Dim i As Integer
  66. Dim j As Integer
  67. Dim factor As Single
  68. Dim tmp As Single
  69.     max_row = UBound(coeff, 1)
  70.     max_col = UBound(coeff, 2)
  71.     For row = 0 To max_row
  72.         ' Make sure coeff(row, row) <> 0.
  73.         factor = coeff(row, row)
  74.         If Abs(factor) < 0.001 Then
  75.             ' Switch this row with one that is not
  76.             ' zero in position. Find this row.
  77.             For i = row + 1 To max_row
  78.                 If Abs(coeff(i, row) > 0.001) Then
  79.                     ' Switch rows i and row.
  80.                     For j = 0 To max_col
  81.                         tmp = coeff(row, j)
  82.                         coeff(row, j) = coeff(i, j)
  83.                         coeff(i, j) = tmp
  84.                     Next j
  85.                     factor = coeff(row, row)
  86.                 End If
  87.             Next i
  88.             ' See if we found a good row.
  89.             If Abs(factor) < 0.001 Then
  90.                 ' We found no good row.
  91.                 ' There is no solution.
  92.                 GaussianEliminate = False
  93.                 Exit Function
  94.             End If
  95.         End If
  96.         ' Divide each entry in this row by
  97.         ' coeff(row, row).
  98.         For i = 0 To max_col
  99.             coeff(row, i) = coeff(row, i) / factor
  100.         Next i
  101.         ' Subtract this row from the others.
  102.         For i = 0 To max_row
  103.             If i <> row Then
  104.                 ' See what factor we will multiply
  105.                 ' by before subtracting for this row.
  106.                 factor = coeff(i, row)
  107.                 For j = 0 To max_col
  108.                     coeff(i, j) = coeff(i, j) - factor * coeff(row, j)
  109.                 Next j
  110.             End If
  111.         Next i
  112.     Next row
  113.     ' There is a solution.
  114.     GaussianEliminate = True
  115. End Function
  116. ' Compute the a, b, and c values for quadratic least squares.
  117. ' Return True if there is a solution.
  118. Private Function GetLeastSquaresValues(ByVal degree As Integer, X() As Single, Y() As Single, a_values() As Single) As Boolean
  119. Dim max_point As Integer
  120. Dim coeff() As Single
  121. Dim row As Integer
  122. Dim col As Integer
  123. Dim i As Integer
  124. Dim total As Single
  125.     max_point = UBound(X) - 1
  126.     ' Find the coefficients for the equations.
  127.     ReDim coeff(0 To degree, 0 To degree + 1)
  128.     For row = 0 To degree
  129.         ' Find the coefficients for the columns.
  130.         For col = 0 To degree
  131.             ' Find Sum(Xi^(row + col)) over all i.
  132.             total = 0
  133.             For i = 0 To max_point
  134.                 total = total + X(i + 1) ^ (row + col)
  135.             Next i
  136.             coeff(row, col) = total
  137.         Next col
  138.         ' Find the constant term.
  139.         total = 0
  140.         For i = 0 To max_point
  141.             total = total + Y(i + 1) * X(i + 1) ^ row
  142.         Next i
  143.         coeff(row, degree + 1) = total
  144.     Next row
  145.     ' Perform the Gaussian elimination.
  146.     If GaussianEliminate(coeff) Then
  147.         ' There is a solution.
  148.         ' Save the results.
  149.         ReDim a_values(0 To degree)
  150.         For row = 0 To degree
  151.             a_values(row) = coeff(row, degree + 1)
  152.         Next row
  153.         GetLeastSquaresValues = True
  154.     Else
  155.         ' There is no solution.
  156.         GetLeastSquaresValues = False
  157.     End If
  158. End Function
  159. ' Find the value of the polynomial with the given
  160. ' coefficients.
  161. Private Function PolynomialValue(a_values() As Single, ByVal X As Single) As Single
  162. Dim max_coeff As Integer
  163. Dim total As Single
  164. Dim i As Integer
  165. Dim x_power As Single
  166.     max_coeff = UBound(a_values)
  167.     x_power = 1#
  168.     For i = 0 To max_coeff
  169.         total = total + x_power * a_values(i)
  170.         x_power = x_power * X
  171.     Next i
  172.     PolynomialValue = total
  173. End Function
  174. Private Sub Form_Resize()
  175. Dim hgt As Single
  176.     cmdGo.Move (ScaleWidth - cmdGo.Width) / 2, ScaleHeight - cmdGo.Height
  177.     Label1.Top = cmdGo.Top
  178.     txtDegree.Top = cmdGo.Top
  179.     hgt = cmdGo.Top - 30
  180.     If hgt < 120 Then hgt = 120
  181.     picCanvas.Move 0, 0, ScaleWidth, hgt
  182. End Sub
  183. ' Add this point to the list of points.
  184. Private Sub picCanvas_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  185. Const GAP = 2
  186.     ' If this is the first point, erase the screen.
  187.     If NumPts < 1 Then picCanvas.Cls
  188.     ' Record the new point.
  189.     NumPts = NumPts + 1
  190.     ReDim Preserve PtX(1 To NumPts)
  191.     ReDim Preserve PtY(1 To NumPts)
  192.     PtX(NumPts) = X
  193.     PtY(NumPts) = Y
  194.     ' Display the point.
  195.     picCanvas.Line (X - GAP, Y - GAP)-(X + GAP, Y + GAP), , BF
  196.     ' If NumPts >= 2, enable the Go button.
  197.     If NumPts >= 2 Then cmdGo.Enabled = True
  198. End Sub
  199. ' Draw the least squares fit curve.
  200. Private Sub cmdGo_Click()
  201. Dim degree As Integer
  202.     cmdGo.Enabled = False
  203.     degree = CInt(txtDegree.Text)
  204.     ' There's no point making degree >= NumPts.
  205.     If degree >= NumPts Then
  206.         degree = NumPts - 1
  207.         txtDegree.Text = Format$(degree)
  208.     End If
  209.     DrawCurve degree
  210.     ' Prepare to get a new set of points.
  211.     NumPts = 0
  212. End Sub
  213. ' Draw the least squares line.
  214. Private Sub DrawCurve(ByVal degree As Integer)
  215. Dim a_values() As Single
  216. Dim x1 As Single
  217. Dim x2 As Single
  218. Dim i As Integer
  219. Dim X As Single
  220. Dim dx As Single
  221.     ' Get the parameters for the quadratic.
  222.     If GetLeastSquaresValues(degree, PtX, PtY, a_values) Then
  223.         ' There is a solution.
  224.         ' Find the minimum and maximum X values.
  225.         x1 = PtX(1) ' This will be the minimum X value.
  226.         x2 = x1     ' This will be the maximum X value.
  227.         For i = 2 To NumPts
  228.             If x1 > PtX(i) Then x1 = PtX(i)
  229.             If x2 < PtX(i) Then x2 = PtX(i)
  230.         Next i
  231.         ' Draw the curve.
  232.         picCanvas.CurrentX = x1
  233.         picCanvas.CurrentY = PolynomialValue(a_values, x1)
  234.         ' Make dx = 1 pixel.
  235.         dx = picCanvas.ScaleX(1, vbPixels, picCanvas.ScaleMode)
  236.         X = x1 + dx
  237.         Do While X < x2
  238.             picCanvas.Line -(X, PolynomialValue(a_values, X))
  239.             X = X + dx
  240.         Loop
  241.         picCanvas.Line -(x2, PolynomialValue(a_values, x2))
  242.     Else
  243.         ' There is no solution.
  244.         MsgBox "There is no solution."
  245.     End If
  246. End Sub
  247.